home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / linuxdoc-sgml-1.1 / sgmls-1.1 / rast.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-03  |  10.8 KB  |  535 lines

  1. /* rast.c
  2.    Translate sgmls output to RAST result format.
  3.  
  4.    Written by James Clark (jjc@jclark.com). */
  5.  
  6. #include "config.h"
  7. #include "std.h"
  8. #include "sgmls.h"
  9. #include "getopt.h"
  10.  
  11. #ifdef USE_PROTOTYPES
  12. #define P(parms) parms
  13. #else
  14. #define P(parms) ()
  15. #endif
  16.  
  17. #ifdef __GNUC__
  18. #define NO_RETURN volatile
  19. #else
  20. #define NO_RETURN /* as nothing */
  21. #endif
  22.  
  23. #ifdef VARARGS
  24. #define VP(parms) ()
  25. #else
  26. #define VP(parms) P(parms)
  27. #endif
  28.  
  29. #ifdef USE_ISASCII
  30. #define ISASCII(c) isascii(c)
  31. #else
  32. #define ISASCII(c) (1)
  33. #endif
  34.  
  35. NO_RETURN void error VP((char *,...));
  36.  
  37. static void input_error P((int, char *, unsigned long));
  38. static int do_file P((FILE *));
  39. static void usage P((void));
  40.  
  41. static void output_processing_instruction P((char *, unsigned));
  42. static void output_data P((struct sgmls_data *, int));
  43. static void output_data_lines P((char *, unsigned));
  44. static void output_internal_sdata P((char *, unsigned));
  45. static void output_external_entity P((struct sgmls_external_entity *));
  46. static void output_external_entity_info P((struct sgmls_external_entity *));
  47. static void output_element_start P((char *, struct sgmls_attribute *));
  48. static void output_element_end P((char *));
  49. static void output_attribute P((struct sgmls_attribute *));
  50. static void output_tokens P((char **, int));
  51. static void output_markup_chars P((char *, unsigned));
  52. static void output_markup_string P((char *));
  53. static void output_char P((int, int));
  54. static void output_flush P((int));
  55. static void output_external_id P((char *, char *));
  56. static void output_entity P((struct sgmls_entity *));
  57. static void output_external_entity_info P((struct sgmls_external_entity *));
  58. static void output_internal_entity P((struct sgmls_internal_entity *));
  59.  
  60. #define output_flush_markup() output_flush('!')
  61. #define output_flush_data() output_flush('|')
  62.  
  63. static FILE *outfp;
  64. static int char_count = 0;
  65. static char *program_name;
  66.  
  67. int main(argc, argv)
  68.      int argc;
  69.      char **argv;
  70. {
  71.   int c;
  72.   int opt;
  73.   char *output_file = 0;
  74.  
  75.   program_name = argv[0];
  76.  
  77.   while ((opt = getopt(argc, argv, "o:")) != EOF)
  78.     switch (opt) {
  79.     case 'o':
  80.       output_file = optarg;
  81.       break;
  82.     case '?':
  83.       usage();
  84.     default:
  85.       abort();
  86.     }
  87.  
  88.   if (output_file) {
  89.     errno = 0;
  90.     outfp = fopen(output_file, "w");
  91.     if (!outfp)
  92.       error("couldn't open `%s' for output: %s", strerror(errno));
  93.   }
  94.   else {
  95.     outfp = tmpfile();
  96.     if (!outfp)
  97.       error("couldn't create temporary file: %s", strerror(errno));
  98.   }
  99.  
  100.   if (argc - optind > 1)
  101.     usage();
  102.  
  103.   if (argc - optind == 1) {
  104.     if (!freopen(argv[optind], "r", stdin))
  105.       error("couldn't open `%s' for input: %s", argv[optind], strerror(errno));
  106.   }
  107.  
  108.   (void)sgmls_set_errhandler(input_error);
  109.  
  110.   if (!do_file(stdin)) {
  111.     fclose(outfp);
  112.     if (output_file) {
  113.       if (!freopen(output_file, "w", stdout))
  114.     error("couldn't reopen `%s' for output: %s", strerror(errno));
  115.     }
  116.     fputs("#ERROR\n", stdout);
  117.     exit(EXIT_FAILURE);
  118.   }
  119.  
  120.   if (output_file) {
  121.     errno = 0;
  122.     if (fclose(outfp) == EOF)
  123.       error("error closing `%s': %s", output_file, strerror(errno));
  124.   }
  125.   else {
  126.     errno = 0;
  127.     if (fseek(outfp, 0L, SEEK_SET))
  128.       error("couldn't rewind temporary file: %s", strerror(errno));
  129.     while ((c = getc(outfp)) != EOF)
  130.       if (putchar(c) == EOF)
  131.     error("error writing standard output: %s", strerror(errno));
  132.   }
  133.   exit(EXIT_SUCCESS);
  134. }
  135.  
  136. static
  137. void usage()
  138. {
  139.   fprintf(stderr, "usage: %s [-o output_file] [input_file]\n", program_name);
  140.   exit(EXIT_FAILURE);
  141. }
  142.  
  143. static
  144. int do_file(fp)
  145.      FILE *fp;
  146. {
  147.   struct sgmls *sp;
  148.   struct sgmls_event e;
  149.   int conforming = 0;
  150.  
  151.   sp = sgmls_create(fp);
  152.   while (sgmls_next(sp, &e))
  153.     switch (e.type) {
  154.     case SGMLS_EVENT_DATA:
  155.       output_data(e.u.data.v, e.u.data.n);
  156.       break;
  157.     case SGMLS_EVENT_ENTITY:
  158.       output_external_entity(e.u.entity);
  159.       break;
  160.     case SGMLS_EVENT_PI:
  161.       output_processing_instruction(e.u.pi.s, e.u.pi.len);
  162.       break;
  163.     case SGMLS_EVENT_START:
  164.       output_element_start(e.u.start.gi, e.u.start.attributes);
  165.       sgmls_free_attributes(e.u.start.attributes);
  166.       break;
  167.     case SGMLS_EVENT_END:
  168.       output_element_end(e.u.end.gi);
  169.       break;
  170.     case SGMLS_EVENT_SUBSTART:
  171.       {
  172.     int level = 1;
  173.     output_external_entity(e.u.entity);
  174.     while (level > 0) {
  175.       if (!sgmls_next(sp, &e))
  176.         return 0;
  177.       switch (e.type) {
  178.       case SGMLS_EVENT_SUBSTART:
  179.         level++;
  180.         break;
  181.       case SGMLS_EVENT_SUBEND:
  182.         level--;
  183.         break;
  184.       case SGMLS_EVENT_START:
  185.         sgmls_free_attributes(e.u.start.attributes);
  186.         break;
  187.       default:
  188.         /* prevent compiler warnings */
  189.         break;
  190.       }
  191.     }
  192.       }
  193.       break;
  194.     case SGMLS_EVENT_APPINFO:
  195.       break;
  196.     case SGMLS_EVENT_CONFORMING:
  197.       conforming = 1;
  198.       break;
  199.     default:
  200.       abort();
  201.     }
  202.   sgmls_free(sp);
  203.   return conforming;
  204. }
  205.  
  206. static
  207. void output_processing_instruction(s, len)
  208.      char *s;
  209.      unsigned len;
  210. {
  211.   fputs("[?", outfp);
  212.   if (len > 0) {
  213.     putc('\n', outfp);
  214.     output_data_lines(s, len);
  215.     output_flush_data();
  216.   }
  217.   fputs("]\n", outfp);
  218. }
  219.  
  220. static
  221. void output_data(v, n)
  222.      struct sgmls_data *v;
  223.      int n;
  224. {
  225.   int i;
  226.   for (i = 0; i < n; i++) {
  227.     if (v[i].is_sdata)
  228.       output_internal_sdata(v[i].s, v[i].len);
  229.     else if (v[i].len > 0)
  230.       output_data_lines(v[i].s, v[i].len);
  231.   }
  232. }
  233.  
  234. static
  235. void output_data_lines(s, n)
  236.      char *s;
  237.      unsigned n;
  238. {
  239.   assert(n > 0);
  240.   for (; n > 0; --n)
  241.     output_char((unsigned char)*s++, '|');
  242.   output_flush_data();
  243. }
  244.  
  245. static
  246. void output_internal_sdata(s, n)
  247.      char *s;
  248.      unsigned n;
  249. {
  250.   fputs("#SDATA-TEXT\n", outfp);
  251.   output_markup_chars(s, n);
  252.   output_flush_markup();
  253.   fputs("#END-SDATA\n", outfp);
  254. }
  255.  
  256. static
  257. void output_external_entity(e)
  258.      struct sgmls_external_entity *e;
  259. {
  260.   fprintf(outfp, "[&%s\n", e->name);
  261.   output_external_entity_info(e);
  262.   fputs("]\n", outfp);
  263. }
  264.  
  265. static
  266. void output_element_start(gi, att)
  267.      char *gi;
  268.      struct sgmls_attribute *att;
  269. {
  270.   fprintf(outfp, "[%s", gi);
  271.   if (att) {
  272.     struct sgmls_attribute *p;
  273.     putc('\n', outfp);
  274.     for (p = att; p; p = p->next)
  275.       output_attribute(p);
  276.   }
  277.   fputs("]\n", outfp);
  278. }
  279.  
  280. static
  281. void output_element_end(gi)
  282.      char *gi;
  283. {
  284.   fprintf(outfp, "[/%s]\n", gi);
  285. }
  286.  
  287. static
  288. void output_attribute(p)
  289.      struct sgmls_attribute *p;
  290. {
  291.   fprintf(outfp, "%s=\n", p->name);
  292.   switch (p->type) {
  293.   case SGMLS_ATTR_IMPLIED:
  294.     fputs("#IMPLIED\n", outfp);
  295.     break;
  296.   case SGMLS_ATTR_CDATA:
  297.     {
  298.       struct sgmls_data *v = p->value.data.v;
  299.       int n = p->value.data.n;
  300.       int i;
  301.       for (i = 0; i < n; i++)
  302.     if (v[i].is_sdata)
  303.       output_internal_sdata(v[i].s, v[i].len);
  304.     else {
  305.       output_markup_chars(v[i].s, v[i].len);
  306.       output_flush_markup();
  307.     }
  308.     }
  309.     break;
  310.   case SGMLS_ATTR_TOKEN:
  311.     output_tokens(p->value.token.v, p->value.token.n);
  312.     break;
  313.   case SGMLS_ATTR_ENTITY:
  314.     {
  315.       int i;
  316.       for (i = 0; i < p->value.entity.n; i++) {
  317.     struct sgmls_entity *e = p->value.entity.v[i];
  318.     char *name;
  319.  
  320.     if (e->is_internal)
  321.       name = e->u.internal.name;
  322.     else
  323.       name = e->u.external.name;
  324.     if (i > 0)
  325.       output_markup_string(" ");
  326.     output_markup_string(name);
  327.       }
  328.       output_flush_markup();
  329.       for (i = 0; i < p->value.entity.n; i++)
  330.     output_entity(p->value.entity.v[i]);
  331.     }
  332.     break;
  333.   case SGMLS_ATTR_NOTATION:
  334.     output_tokens(&p->value.notation->name, 1);
  335.     output_external_id(p->value.notation->pubid, p->value.notation->sysid);
  336.     break;
  337.   }
  338. }
  339.  
  340. static void output_tokens(v, n)
  341.      char **v;
  342.      int n;
  343. {
  344.   int i;
  345.   assert(n > 0);
  346.   output_markup_string(v[0]);
  347.   for (i = 1; i < n; i++) {
  348.     output_markup_string(" ");
  349.     output_markup_string(v[i]);
  350.   }
  351.   output_flush_markup();
  352. }
  353.  
  354. static
  355. void output_markup_chars(s, n)
  356.      char *s;
  357.      unsigned n;
  358. {
  359.   for (; n > 0; --n)
  360.     output_char((unsigned char)*s++, '!');
  361. }
  362.  
  363. static
  364. void output_markup_string(s)
  365.      char *s;
  366. {
  367.   while (*s)
  368.     output_char((unsigned char)*s++, '!');
  369. }
  370.  
  371. static
  372. void output_char(c, delim)
  373.      int c;
  374.      int delim;
  375. {
  376.   if (ISASCII(c) && isprint(c)) {
  377.     if (char_count == 0)
  378.       putc(delim, outfp);
  379.     putc(c, outfp);
  380.     char_count++;
  381.     if (char_count == 60) {
  382.       putc(delim, outfp);
  383.       putc('\n', outfp);
  384.       char_count = 0;
  385.     }
  386.   }
  387.   else {
  388.     output_flush(delim);
  389.     switch (c) {
  390.     case RECHAR:
  391.       fputs("#RE\n", outfp);
  392.       break;
  393.     case RSCHAR:
  394.       fputs("#RS\n", outfp);
  395.       break;
  396.     case TABCHAR:
  397.       fputs("#TAB\n", outfp);
  398.       break;
  399.     default:
  400.       fprintf(outfp, "#%d\n", c);
  401.     }
  402.   }
  403. }
  404.  
  405. static
  406. void output_flush(delim)
  407.      int delim;
  408. {
  409.   if (char_count > 0) {
  410.     putc(delim, outfp);
  411.     putc('\n', outfp);
  412.     char_count = 0;
  413.   }
  414. }
  415.  
  416. static
  417. void output_external_id(pubid, sysid)
  418.   char *pubid;
  419.   char *sysid;
  420. {
  421.   if (!pubid && !sysid)
  422.     fputs("#SYSTEM\n#NONE\n", outfp);
  423.   else {
  424.     if (pubid) {
  425.       fputs("#PUBLIC\n", outfp);
  426.       if (*pubid) {
  427.     output_markup_string(pubid);
  428.     output_flush_markup();
  429.       }
  430.       else
  431.     fputs("#EMPTY\n", outfp);
  432.     }
  433.     if (sysid) {
  434.       fputs("#SYSTEM\n", outfp);
  435.       if (*sysid) {
  436.     output_markup_string(sysid);
  437.     output_flush_markup();
  438.       }
  439.       else
  440.     fputs("#EMPTY\n", outfp);
  441.     }
  442.   }
  443. }
  444.  
  445. static
  446. void output_entity(e)
  447.      struct sgmls_entity *e;
  448. {
  449.   if (e->is_internal)
  450.     output_internal_entity(&e->u.internal);
  451.   else
  452.     output_external_entity_info(&e->u.external);
  453.   fputs("#END-ENTITY", outfp);
  454. #ifndef ASIS
  455.   putc('\n', outfp);
  456. #endif
  457. }
  458.  
  459. static
  460. void output_external_entity_info(e)
  461.      struct sgmls_external_entity *e;
  462. {
  463.   switch (e->type) {
  464.   case SGMLS_ENTITY_CDATA:
  465.     fputs("#CDATA-EXTERNAL", outfp);
  466.     break;
  467.   case SGMLS_ENTITY_SDATA:
  468.     fputs("#SDATA-EXTERNAL", outfp);
  469.     break;
  470.   case SGMLS_ENTITY_NDATA:
  471.     fputs("#NDATA-EXTERNAL", outfp);
  472.     break;
  473.   case SGMLS_ENTITY_SUBDOC:
  474.     fputs("#SUBDOC", outfp);
  475.     break;
  476.   }
  477.   putc('\n', outfp);
  478.   output_external_id(e->pubid, e->sysid);
  479.   if (e->type != SGMLS_ENTITY_SUBDOC) {
  480.     struct sgmls_attribute *p;
  481.     fprintf(outfp, "#NOTATION=%s\n", e->notation->name);
  482.     output_external_id(e->notation->pubid, e->notation->sysid);
  483.     for (p = e->attributes; p; p = p->next)
  484.       output_attribute(p);
  485.   }
  486. }
  487.  
  488. static
  489. void output_internal_entity(e)
  490.      struct sgmls_internal_entity *e;
  491. {
  492.   if (e->data.is_sdata)
  493.     fputs("#SDATA-INTERNAL", outfp);
  494.   else
  495.     fputs("#CDATA-INTERNAL", outfp);
  496.   putc('\n', outfp);
  497.   output_markup_chars(e->data.s, e->data.len);
  498.   output_flush_markup();
  499. }
  500.  
  501. static
  502. void input_error(num, str, lineno)
  503.      int num;
  504.      char *str;
  505.      unsigned long lineno;
  506. {
  507.   error("Error at input line %lu: %s", lineno, str);
  508. }
  509.  
  510. NO_RETURN
  511. #ifdef VARARGS
  512. void error(va_alist) va_dcl
  513. #else
  514. void error(char *message,...)
  515. #endif
  516. {
  517. #ifdef VARARGS
  518.      char *message;
  519. #endif
  520.      va_list ap;
  521.      
  522.      fprintf(stderr, "%s: ", program_name);
  523. #ifdef VARARGS
  524.      va_start(ap);
  525.      message = va_arg(ap, char *);
  526. #else
  527.      va_start(ap, message);
  528. #endif
  529.      vfprintf(stderr, message, ap);
  530.      va_end(ap);
  531.      fputc('\n', stderr);
  532.      fflush(stderr);
  533.      exit(EXIT_FAILURE);
  534. }
  535.